﻿using System.Diagnostics;
using System.IO;
using System.Windows.Threading;
using FileTransfer.Client.Http.Client;
using FileTransferDesktop.Services;
using FileTransferDesktop.ViewModels.Controls;
using FileTransferDesktop.ViewModels.Pages;
using FileTransferDesktop.ViewModels.Windows;
using FileTransferDesktop.Views.Dialogs;
using FileTransferDesktop.Views.Pages;
using FileTransferDesktop.Views.Windows;
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SkiaSharp;
using Wpf.Ui;
using Wpf.Ui.DependencyInjection;
using AuthDialogViewModel = FileTransferDesktop.ViewModels.Dialogs.AuthDialogViewModel;
using DownloadViewModel = FileTransferDesktop.ViewModels.Pages.DownloadViewModel;

namespace FileTransferDesktop;

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
    // The.NET Generic Host provides dependency injection, configuration, logging, and other services.
    // https://docs.microsoft.com/dotnet/core/extensions/generic-host
    // https://docs.microsoft.com/dotnet/core/extensions/dependency-injection
    // https://docs.microsoft.com/dotnet/core/extensions/configuration
    // https://docs.microsoft.com/dotnet/core/extensions/logging
    private static readonly IHost Host = Microsoft
        .Extensions.Hosting.Host.CreateDefaultBuilder()
        .ConfigureAppConfiguration(c =>
        {
            var baseDirectory = Path.GetDirectoryName(AppContext.BaseDirectory);
            if (baseDirectory != null)
            {
                c.SetBasePath(baseDirectory);
            }
        })
        .ConfigureServices(
            (context, services) =>
            {
                services.AddNavigationViewPageProvider();

                services.AddHostedService<ApplicationHostService>();                // Theme manipulation
                services.AddSingleton<IThemeService, ThemeService>(); // TaskBar manipulation
                services.AddSingleton<ITaskBarService, TaskBarService>();

                // Tray service
                services.AddSingleton<ITrayService, TrayService>();

                // Snackbar service
                services.AddSingleton<ISnackbarService, SnackbarService>(); // Authentication service
                services.AddSingleton<IAuthenticationService, AuthenticationService>();

                // App settings service
                services.AddSingleton<IAppSettingsService, AppSettingsService>();

                // API client configuration (使用认证配置)
                services.AddSingleton<Configuration>(provider =>
                {
                    var authenticationService = provider.GetService<IAuthenticationService>();
                    Debug.Assert(
                        authenticationService != null,
                        nameof(authenticationService) + " != null"
                    );
                    return new AuthenticatedApiConfiguration(authenticationService);
                });

                // Service containing navigation, same as INavigationWindow... but without window
                services.AddSingleton<INavigationService, NavigationService>();

                // Main window with navigation
                services.AddSingleton<INavigationWindow, MainWindow>();
                services.AddSingleton<MainWindowViewModel>();
                services.AddSingleton<DashboardPage>();
                services.AddSingleton<DashboardViewModel>();
                services.AddSingleton<SettingsPage>();
                services.AddSingleton<SettingsViewModel>();
                services.AddSingleton<DownloadPage>();
                services.AddSingleton<DownloadViewModel>();
                services.AddSingleton<UploadPage>();
                services.AddSingleton<UploadViewModel>();
                services.AddSingleton<AboutPage>();
                services.AddSingleton<AboutViewModel>();
                services.AddSingleton<ManagementPage>();
                services.AddSingleton<ManagementViewModel>();
                services.AddSingleton<UserProfilePage>();
                services.AddSingleton<UserProfileViewModel>();
                services.AddSingleton<AuthDialogViewModel>();
                services.AddTransient<AuthDialogControl>();
                services.AddSingleton<UserMenuControlViewModel>();
                services.AddSingleton<WinFormsIntegrationPage>();
                services.AddSingleton<WinFormsIntegrationViewModel>();
            }
        )
        .Build();

    /// <summary>
    /// Gets services.
    /// </summary>
    public static IServiceProvider Services => Host.Services;

    /// <summary>
    /// Occurs when the application is loading.
    /// </summary>
    private async void OnStartup(object sender, StartupEventArgs e)
    {
        try
        {
            await Host.StartAsync();
            LiveCharts.Configure(config =>
            {
                var typeface = SKTypeface.FromFamilyName("Microsoft YaHei");

                config.HasGlobalSKTypeface(typeface);
            });
        }
        catch (Exception exception)
        {
            Debug.WriteLine($"Error during startup: {exception.Message}");
        }
    }

    /// <summary>
    /// Occurs when the application is closing.
    /// </summary>
    private async void OnExit(object sender, ExitEventArgs e)
    {
        try
        {
            await Host.StopAsync();

            Host.Dispose();
        }
        catch (Exception exception)
        {
            Debug.WriteLine($"Error during startup: {exception.Message}");
        }
    }

    /// <summary>
    /// Occurs when an exception is thrown by an application but not handled.
    /// </summary>
    private void OnDispatcherUnhandledException(
        object sender,
        DispatcherUnhandledExceptionEventArgs e
    )
    {
        // For more info see https://docs.microsoft.com/en-us/dotnet/api/system.windows.application.dispatcherunhandledexception?view=windowsdesktop-6.0
    }
}
